package com.kim.common.utilcom.exception;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 业务异常
 *
 * <p>业务异常直接继承于{@link RuntimeException} 为运行时异常
 * 异常文件为{@code business-exceptions.properties} 初次类初始化时会把配置文件加载到包私有Map 中
 *
 * @deprecated 感觉用法有点过时
 */
@Deprecated
@Slf4j
public class BusinessException extends RuntimeException {
    
	private static final long serialVersionUID = -4648879327187605014L;

    /**
     * 异常存储map
     */
    protected static Map<String, String> CODES_MAP = null;

    /**
     * 默认错误消息
     */
    private static final String DEFAULT_ERROR_CODE_MESSAGE = "系统内部错误";

    /**
     * 文件名称
     */
    private static final String EXCEPTION_MESSAGE_PROPERTIES = "business-exceptions.properties";

    // 静态块初始化
    static {
        BusinessException.init();
    }

    /**
     * 从properties配置文件中初始化CodeMap
     */
    private synchronized static void init() {
        if (MapUtils.isEmpty(BusinessException.CODES_MAP)) {
            // 初始化CODE_MAP
            BusinessException.CODES_MAP = new HashMap<>(256);
            BusinessException.CODES_MAP.put("system_error", BusinessException.DEFAULT_ERROR_CODE_MESSAGE);

            PropertiesConfiguration config = null;
            try (InputStream in = BusinessException.class.getClassLoader().getResourceAsStream(BusinessException.EXCEPTION_MESSAGE_PROPERTIES)) {
                config = new PropertiesConfiguration();
                config.setEncoding("utf8");
                config.load(in);
            } catch (ConfigurationException e) {
                log.error("[business exception] get pro file error:", e);
            } catch (IOException e) {
                log.error("[business exception] ", e);
            }
            log.info("[business exception] init start...");

            Iterator<?> keyIterator = config.getKeys();
            while (keyIterator.hasNext()) {
                String key = (String) keyIterator.next();
                BusinessException.CODES_MAP.put(key, config.getString(key));
                log.info("[business exception] add exception:code= {} ,message= {}",key, config.getString(key));
            }

            log.info("[business exception] init exception map suc.");
        }
    }

    /**
     * 本异常错误代码
     */
    private String errorCode;
    /**
     * 附加描述信息
     */
    private String additionMessage;

  
    /**
     * 异常状态码、异常消息 构造器
     * @param errCode 异常状态码
     * @param additionMessage  异常消息       
     */
    public BusinessException(String errCode, String additionMessage) {
        super(additionMessage);
        this.errorCode = errCode;
        this.additionMessage = additionMessage;
    }
    
    /**
     * 异常状态码 构造器
     * @param errCode 异常状态码
     */
    public BusinessException(String errCode) {
        super();
        errorCode = errCode;
    }

    /**
     * 异常状态码，消息，异常对象 构造器
     * @param errCode 异常状态码
     */
    public BusinessException(String errCode, String additionMessage, Throwable cause) {
        super(cause);
        errorCode = errCode;
        this.additionMessage = additionMessage;
    }

    /**
     * 异常状态码，异常对象 构造器
     * @param errCode 异常状态码
     */
    public BusinessException(String errCode, Throwable cause) {
        super(cause);
        errorCode = errCode;
    }

    /**
     * 获取异常错误代码
     * @return java.lang.String 异常错误代码
     */
    public String getErrorCode() {
        return errorCode;
    }

    /**
     * 消息本地化
     * @inheritDoc
     * @return java.lang.String
     */
    @Override
    public String getMessage() {
        return getLocalizedMessage();
    }

    /**
     * 如果此对象未指定消息且配置文件中未定义设置未默认错误
     * @return java.lang.String 异常消息
     */
    @Override
    public String getLocalizedMessage() {
        String message;
        return  null != this.additionMessage
                ? this.additionMessage
                : StringUtils.isEmpty(message = BusinessException.CODES_MAP.get(this.errorCode))
                ? DEFAULT_ERROR_CODE_MESSAGE :message ;
    }
}
